package com.darwin.darwinBitmapEngine.core
{
	import com.darwin.darwinBitmapEngine.utils.G_ID;
	
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * 容器节点。ContainerNode可被添加INode,即可以包含多个显示对象。
	 * 但ContainerNode不同于player api中的容器，ContainerNode设计来作用多个节点的集合体，
	 * ContainerNode不允许被嵌套，通常应该手动控制每一个子节点
	 * @author lipi
	 */
	public class ContainerNode extends EventDispatcher implements INode,IContainer
	{
		public function ContainerNode()
		{
			_nodeList = new Vector.<INode>();
			_g_ID = G_ID.id;
		}
		
		private var _g_ID:uint;
		public function get g_ID():uint
		{
			return _g_ID;
		}
		
		
		/**
		 * 对于ContainerNode类此属性无效，请使用ContainerNode类的addNode添加显示对象
		 * @return 
		 */
		public function get bitmapData():BitmapData
		{
			return null;
		}
		
		public function set bitmapData(value:BitmapData):void
		{
		}
		
		
		public function render():void
		{
			
		}
		
		private var _renderNotify:Boolean = false;
		
		/**
		 *	执行渲染完成通知 (如果renderNotify为true，则此方法会再本帧渲染完成后被调用)
		 */
		public function exeRenderNotify():void
		{
			
		}
		
		/**
		 *	是否需要在渲染完成之后接收渲染完成通知
		 * @param value
		 * 
		 */
		public function set renderNotify(value:Boolean):void
		{
			_renderNotify = value;
		}
		
		public function get renderNotify():Boolean
		{
			return _renderNotify;
		}
		
		
		
		
		private var _rect:Rectangle;
		
		public function set rect(value:Rectangle):void
		{
			_rect = value;
		}
		
		public function get rect():Rectangle
		{
			caculateRect();
			return _rect;
		}
		
		
		
		public function get width():Number
		{
			caculateRect();
			return rect.width;
		}
		
		
		public function get height():Number
		{
			caculateRect();
			return rect.height;
		}
		
		private var _parent:IContainer;
		
		/**
		 * 设置所在的父级
		 */
		public function set parentContainer(value:IContainer):void
		{
			_parent = value;
		}
		
		public function get parentContainer():IContainer
		{
			return _parent;
		}
		
		
		/**
		 * 如果一个节点位置和大小改变则标记它
		 */
		public function markChange(node:INode):INode
		{
			if(this.parentContainer)
			{
				this.parentContainer.markChange(node);
			}
			_rectChanged = true;
			return node;
		}
		
		private var _rectChanged:Boolean = false;
		private function caculateRect():void
		{
			if(_rect==null)_rect = new Rectangle();
			if(_rectChanged)
			{
				_rect.x = 0;
				_rect.y = 0;
				_rect.width = 0;
				_rect.height = 0;
				for (var i:int = 0; i < _nodeList.length; i++) 
				{
					if(_nodeList[i].rect)
					{
						var childRect:Rectangle = _nodeList[i].rect.clone();
						childRect.x = _nodeList[i].x;
						childRect.y = _nodeList[i].y;
						_rect = _rect.union(childRect);
					}
				}
				_rectChanged = false;
			}
		}
		
		///////////////////////////////////////////////////
		
		//显示列表操作 
		
		//////////////////////////////////////////////////
		
		//显示列表 
		protected var _nodeList:Vector.<INode>;
		
		/**
		 * @return 返回列表项个数
		 */
		public function get numChildren():uint
		{
			return _nodeList.length;
		}
		
		/**
		 * 添加一个显示对象到显示列表
		 * @param node 对象节点
		 * @return 返回对象节点
		 */
		public function addNode(node:INode):INode
		{
//			node.clickEnabled = this.clickEnabled;
//			node.mouseHoverEnabled = this.mouseHoverEnabled;
			_nodeList.push(node);
			if(node.parentContainer != null) node.parentContainer.removeNode(node);
			node.parentContainer = this;
			markChange(this);
			return node;
		}
		
		/**
		 * 删除一个节点
		 * @param node 要删除的节点
		 * @return 被删除的节点
		 */
		public function removeNode(node:INode):INode
		{
			var $length:int = _nodeList.length;
			var found:Boolean = false;
			for(var i:int = 0;i<$length;i++)
			{
				if(_nodeList[i] == node)
				{
					_nodeList.splice(i,1);
					node.parentContainer = null;
					found = true;
					break;
				}
			}
			markChange(this);
			if(found)
				return node;
			else
				return null;
		}
		
		
		/**
		 * 添加一个节点到某个索引 
		 * @param node 要添加的节点 
		 * @param index 要加到的索引
		 * @return 添加的节点
		 */
		public function addNodeAt(node:INode,index:int):INode
		{
//			node.clickEnabled = this.clickEnabled;
//			node.mouseHoverEnabled = this.mouseHoverEnabled;
			_nodeList.splice(index,0,node);
			if(node.parentContainer != null) node.parentContainer.removeNode(node);
			node.parentContainer = this;
			markChange(this);
			return node;
		}
		
		/**
		 * 删除某个索引的节点
		 * @param index 
		 * @return 
		 */
		public function removeNodeAt(index:int):INode
		{
			var $nodeList:Vector.<INode> =  _nodeList.splice(index,1) as Vector.<INode>;
			var $node:INode = $nodeList[0];
			$node.parentContainer = null;
			markChange(this);
			return $node;
		}
		
		/**
		 * 删除所有节点 
		 * 
		 */		
		public function removeAllNode():void
		{
			while(numChildren)
			{
				removeNodeAt(0);
				markChange(this);
			}
		}
		
		
		/**
		 * 取得位于某个索引中的节点
		 * @param index 索引值
		 * @return 返回某个索引的节点
		 */
		public function getNodeAt(index:int):INode
		{
			return _nodeList[index];
		}

		//\\\显示列表结束\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		
		private var _clickEnabled:Boolean = false;
		/**
		 * 是否允许单击
		 */
		public function set clickEnabled(value:Boolean):void
		{
			for(var i:int = 0;i<_nodeList.length;i++)
			{
				_nodeList[i].clickEnabled = value;
			}
			_clickEnabled = value;
		}
		public function get clickEnabled():Boolean
		{
			return _clickEnabled;
		}
		
		private var _mouseHoverEnabled:Boolean = false;
		/**
		 * 是否允许鼠标滑入滑出
		 */
		public function set mouseHoverEnabled(value:Boolean):void
		{
			for(var i:int = 0;i<_nodeList.length;i++)
			{
				_nodeList[i].mouseHoverEnabled = value;
			}
			_mouseHoverEnabled = value;
		}
		public function get mouseHoverEnabled():Boolean
		{
			return _mouseHoverEnabled;
		}
		
		
		
		private var _x:Number = 0;
		/**
		 * 2D x坐标
		 * @param value
		 */
		public function set x(value:Number):void
		{
			if(_x != value)
			{
				_x = value;
				markChange(this);
			}
//			for(var i:int = 0;i<_nodeList.length;i++)
//			{
//				markChange(_nodeList[i]);
//			}
		}
		
		public function get x():Number
		{
			return _x;
		}
		
		private var _y:Number = 0;
		/**
		 * 2D y坐标
		 * @param value
		 */
		public function set y(value:Number):void
		{
			if(_y != value)
			{
				_y = value;
				markChange(this);
			}
//			for(var i:int = 0;i<_nodeList.length;i++)
//			{
//				markChange(_nodeList[i]);
//			}
		}
		
		public function get y():Number
		{
			return _y;
		}
		
		
		private var _visible:Boolean = true;
		
		/**
		 * 是否可见
		 */
		public function set visible(value:Boolean):void
		{
			if(_visible != value)
			{
				_visible = value;
				markChange(this);
			}
		}
		
		public function get visible():Boolean
		{
			return _visible;
		}
		
		/** 
		 * 检测是否碰撞 
		 * @param x 节点x坐标 
		 * @param y 节点y坐标 
		 * @param alphaThreshold 透明度检测，小于这个透明值的将被忽略
		 */
		public function hitTest(x:Number,y:Number,alphaThreshold:uint = 0x00):Boolean
		{
			return false;
		}
		
		public function localToGlobal(point:Point):Point
		{
			var newPoint:Point = new Point();
			if(canvas){
				var canvasGlobalPoint:Point = canvas.localToGlobal(new Point);
				newPoint = new Point(x + point.x + canvas.contentX + canvasGlobalPoint.x,y + point.y + canvas.contentY + canvasGlobalPoint.y);
			}
			return newPoint; 
		}
		
		/**
		 *	获取负责绘制自己的画布 
		 * @return 
		 * 
		 */
		private function get canvas():Canvas
		{
			if(parentContainer && parentContainer is Canvas)
			{
				return parentContainer as Canvas;
			}
			return null;
		}
	}
}